package com.msgc.utils.crypto.config;

import com.msgc.utils.crypto.asymmetric.factory.AsymmetricKeyPairFactory;
import com.msgc.utils.crypto.asymmetric.processor.DefaultAsymmetricCryptoProcessor;
import com.msgc.utils.crypto.asymmetric.store.KeyPairCache;
import com.msgc.utils.crypto.asymmetric.store.impl.LocalKeyPairCache;
import com.msgc.utils.crypto.asymmetric.store.impl.RedisKeyPairCache;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.security.Security;

/**
 * 非对称加密配置，默认使用ECC作为非对称加密
 * @author Admin
 */
@Configuration
public class AsymmetricCryptoConfiguration {

    // BC
    static {
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    /** 算法实现提供商 */
    @Value("${crypto.symmetric.provider:BC}")
    private String provider;

    /** 算法名称 */
    @Value("${crypto.symmetric.algorithm:EC}")
    private String algorithm;

    /** 秘钥位数 */
    @Value("${crypto.symmetric.keyLength:256}")
    private int keyLength;

    /** 算法实现 */
    @Value("${crypto.symmetric.transformation:ECIES}")
    private String transformation;

    /** 签名算法名称 */
    @Value("${crypto.symmetric.signatureAlgorithm:SHA256withECDSA}")
    private String signatureAlgorithm;

    @Value("${spring.application.name:nullApplicationName}")
    String applicationName;

    @Bean("redisKeyPairCache")
    @ConditionalOnProperty(name = "msgc.cluster", havingValue = "true")
    @ConditionalOnBean(RedisTemplate.class)
    public KeyPairCache redisKeyPairCache(RedisTemplate<String, Object> redisTemplate){

        return new RedisKeyPairCache(
                redisTemplate,
                new AsymmetricKeyPairFactory(algorithm, keyLength, provider)
                , applicationName + "-crypto-" + algorithm
        );
    }

    @Bean("localKeyPairCache")
    @ConditionalOnMissingBean(value = {RedisKeyPairCache.class})
    public KeyPairCache localKeyPairCache(){
        return new LocalKeyPairCache();
    }

    @Bean
    public DefaultAsymmetricCryptoProcessor asymmetricProcessor(KeyPairCache keyPairCache){
        return new DefaultAsymmetricCryptoProcessor(
                algorithm,
                keyLength,
                transformation,
                signatureAlgorithm,
                provider,
                keyPairCache
        );
    }
}
